package gui;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.KeyStroke;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import psim.Main;

/**
 *Trida, ktera zajistuje gui - tj hlavni okno a volani prislusnych
 * obsluznych rutin.
 * @author Tomas Drimal
 */
public class Gui {

    public static File actFile;
    public static JMenuItem menuReopen = null;
    public static JLabel lCpsPMs;
    public static JSpinner spinSteps;
    private static JMenu submenu;
    private static JRadioButtonMenuItem rbMenuItem;
    public boolean clrCanvas = false;
    public static JButton btnPlay0;
    public static JButton btnPlay;
    public static About AboutFrame;
    public static Canvas platno;

//    public static final double REAL_WIDTH = 1.2e13;
//    public static final double REAL_HEIGHT = 1.2e13;
//    Canvas c;
    public static void createAndShowGUI() {
        //Hlavni okno
        JFrame mainFrame = new JFrame("Particle simulator");
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridBagConstraints c = new GridBagConstraints();
        mainFrame.setLayout(new GridBagLayout());
        //zobrazení okna
//                mainFrame.setSize(psim.Main.CLIENT_WIDTH_PX, psim.Main.CLIENT_HEIGHT_PX);
        final SConsts consFrame = new SConsts();
        AboutFrame = new About();
        AboutFrame.setLocationRelativeTo(null);

        //panel, na kterem se zobrazuji castice
        platno = new Canvas();
//        nastaveni pozice v mrizce (0,0)
        c.gridx = 0;
        c.gridy = 0;
//        roztazeni na celou sirku a vysku
        c.weightx = 1;
        c.weighty = 1;
        c.fill = GridBagConstraints.BOTH;
//        Pridani platna do okna
        mainFrame.add(platno, c);
        //separator
        c.weightx = 0;
        c.weighty = 0;
        c.gridy = 1;
        mainFrame.add(new JSeparator(SwingConstants.HORIZONTAL), c);
        //panel s ovladacimi prvky
//        panel se s ridicimi komponentami
        JPanel bottomPane = new JPanel(new BorderLayout());
//        Pole pro vypisovani informaci o rychlosti vypisovani
        lCpsPMs = new JLabel("0 cpms");
        lCpsPMs.setSize(30, lCpsPMs.getHeight());
//        Pridani na spodni panel
        bottomPane.add(lCpsPMs, BorderLayout.WEST);
//        panel se zbytkem komponent
        JPanel stepsPane = new JPanel();
//        text:
        JLabel lSteps = new JLabel("Nr. of steps: ");
        stepsPane.add(lSteps);
//        spinner model - nastaveni spinneru pro pocet kroku
        SpinnerModel model =
                new SpinnerNumberModel(100, //initial value
                1, //min
                100000000, //max
                10);
//        Spinner s poctem kroku
        spinSteps = new JSpinner(model);
//        Pridani sineru na panel
        stepsPane.add(spinSteps);
//        Tlacitko pro provedeni pozadovaneho poctu kroku
        btnPlay0 = new JButton(">|");
        btnPlay0.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent e) {
                btnPlay0.setEnabled(false);
                btnPlay.setEnabled(false);
                Main.nrOfSteps = Long.valueOf(
                        spinSteps.getModel().getValue().toString());
//                System.out.println(Main.nrOfSteps);
                Main.simulation = true;
            }
        });
        //Pridani na panel
        stepsPane.add(btnPlay0);
        //tlacitko pro spusteni a pozastaveni simulace
        btnPlay = new JButton(">");
        btnPlay.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent e) {
                psim.Main.simulation = !psim.Main.simulation;
                if (Main.simulation) {
                    btnPlay.setText("||");
                } else {
                    btnPlay.setText(">");
                }
            }
        });
        //pridani tlacitka
        stepsPane.add(btnPlay);
//        pridani panelu s ovladacimi prvky na spodni panel
        bottomPane.add(stepsPane, BorderLayout.EAST);
//        Nastavemi GridBagConstraints pro pridani spodniho panelu
        c.fill = GridBagConstraints.HORIZONTAL;
        c.ipady = 0;       //reset to default
        c.gridy = 2;
        c.anchor = GridBagConstraints.WEST; //bottom of space
        c.insets = new Insets(0, 0, 0, 0);  //zero padding padding
//        Pridani spodniho panelu na hlavni panel
        mainFrame.add(bottomPane, c);
        mainFrame.pack();
//         c=new Canvas();
//         mainFrame.add(c);

        ////////////////////////////////////////////////////////////////////
        //pridani hlavniho menu//////////
        //Deklarace instanci
        final JMenuBar mainMenu;
        JMenu menuFile;
        JMenu menuSimulation;
//                JMenu menuPtcs;
        JMenu menuAbout;
        JMenuItem menuOpen;

        JMenuItem menuSave;
        JMenuItem menuCSV;
        JMenuItem menuQuit;
        JMenuItem menuSConstants;
        JMenuItem menuClrTraces;
        JMenuItem menuItAbout;
        final JCheckBoxMenuItem menuVTraces;
        //

        //Create the menu bar.
        mainMenu = new JMenuBar();

        //Build the File menu.
        menuFile = new JMenu("File");
        menuFile.setMnemonic(KeyEvent.VK_F);

        //Build the Simulation menu.
        menuSimulation = new JMenu("Simulation");
        menuSimulation.setMnemonic(KeyEvent.VK_S);

        //Build the About menu.
        menuAbout = new JMenu("About");
        menuAbout.setMnemonic(KeyEvent.VK_B);

        menuOpen = new JMenuItem("Open...",
                KeyEvent.VK_T);
        menuOpen.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_O, ActionEvent.CTRL_MASK));
        menuOpen.getAccessibleContext().setAccessibleDescription(
                "Open the file..");
        menuOpen.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                psim.Main.simulation = false;
                btnPlay.setText(">");
                JFileChooser fc = new JFileChooser();
                fc.setFileFilter(new PtcsFFilter());

                if (fc.showOpenDialog(platno) == JFileChooser.APPROVE_OPTION) {
                    Main.particles.LoadFromFile(fc.getSelectedFile().toString());
                    Main.clrCanvas = true;
                    Main.clrTraces = true;
                    //nastaveni pro moznost reotevreni souboru
                    actFile = new File(fc.getSelectedFile().toString());
                    menuReopen.setText("Reopen " + actFile.getName());
                    menuReopen.setEnabled(true);
                    platno.repaint();
                }
            }
        });
        menuFile.add(menuOpen);

        menuReopen = new JMenuItem("Reopen",
                KeyEvent.VK_T);
        menuReopen.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_R, ActionEvent.CTRL_MASK));
        menuReopen.getAccessibleContext().setAccessibleDescription(
                "Open the file..");
        menuReopen.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                psim.Main.simulation = false;
                btnPlay.setText(">");
                try {
                    Thread.sleep(50);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Gui.class.getName()).log(Level.SEVERE, null, ex);
                }
                Main.particles.LoadFromFile(actFile.toString());
                Main.clrCanvas = true;
                Main.clrTraces = true;

            }
        });
        menuReopen.setEnabled(false);
        menuFile.add(menuReopen);

        menuFile.addSeparator();

        menuSave = new JMenuItem("Save as...",
                KeyEvent.VK_T);
        menuSave.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_S, ActionEvent.CTRL_MASK));
        menuSave.getAccessibleContext().setAccessibleDescription(
                "Save the particles to the file..");
        menuSave.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                if (psim.Main.simulation) {
                    JOptionPane.showMessageDialog(null, "The simulation must be paused!");
                } else {
                    JFileChooser fc = new JFileChooser();
                    fc.setFileFilter(new PtcsFFilter());
                    if (fc.showSaveDialog(platno) == JFileChooser.APPROVE_OPTION) {
                        File f = fc.getSelectedFile();
                        if (f.getName().indexOf('.') == -1) {
                            f = new File(f.getAbsolutePath() + ".pts");
                        }
                        Main.particles.SaveToFile(f.toString());
                    }
                }
            }
        });

        menuFile.add(menuSave);


        menuCSV = new JMenuItem("Export as CSV...",
                KeyEvent.VK_T);
        menuCSV.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_E, ActionEvent.CTRL_MASK));
        menuCSV.getAccessibleContext().setAccessibleDescription(
                "Save the particles to the file..");
        menuCSV.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                if (psim.Main.simulation) {
                    JOptionPane.showMessageDialog(null, "The simulation must be paused!");
                } else {
                    JFileChooser fc = new JFileChooser();
                    fc.setFileFilter(new CSVFFilter());
                    if (fc.showSaveDialog(platno) == JFileChooser.APPROVE_OPTION) {
                        File f = fc.getSelectedFile();
                        if (f.getName().indexOf('.') == -1) {
                            f = new File(f.getAbsolutePath() + ".csv");
                        }
                        try {
                            Main.particles.toCsvFile(f);
                        } catch (FileNotFoundException ex) {
                            Logger.getLogger(Gui.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (IOException ex) {
                            Logger.getLogger(Gui.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
        });

        menuFile.add(menuCSV);

        menuQuit = new JMenuItem("Quit",
                KeyEvent.VK_T);
        menuQuit.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
        menuQuit.getAccessibleContext().setAccessibleDescription(
                "Quit the application");
        menuQuit.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                System.exit(0);
            }
        });
        menuFile.addSeparator();
        menuFile.add(menuQuit);


        //deklarace polozky "set constants" v menu "simulation"
        menuSConstants = new JMenuItem("Set Constants...",
                KeyEvent.VK_T);
        menuSConstants.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_P, ActionEvent.CTRL_MASK));
        menuSConstants.getAccessibleContext().setAccessibleDescription(
                "Sets the global constants");
        menuSConstants.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
//                JOptionPane.showMessageDialog(null, "Je to spravne nastavene");
                consFrame.setVisible(true);
            }
        });
        menuSimulation.add(menuSConstants);
        //konec deklarace polozky "set constants" v menu "simulation"


        menuVTraces = new JCheckBoxMenuItem("Wiev traces");
        menuVTraces.setState(Main.VTraces);
        menuVTraces.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_T, ActionEvent.CTRL_MASK));
        menuVTraces.getAccessibleContext().setAccessibleDescription(
                "Show or hide traces of particles");
        menuVTraces.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                Main.VTraces = menuVTraces.getState();
            }
        });

        menuSimulation.add(menuVTraces);

        //deklarace polozky "clear traces" v menu "simulation"
        menuClrTraces = new JMenuItem("Clear traces",
                KeyEvent.VK_T);
        menuClrTraces.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_D, ActionEvent.CTRL_MASK));
        menuClrTraces.getAccessibleContext().setAccessibleDescription(
                "Clear the traces of particles");
        menuClrTraces.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
//                JOptionPane.showMessageDialog(null, "Je to spravne nastavene");
                Main.clrTraces = true;
            }
        });
        menuSimulation.add(menuClrTraces);
        menuSimulation.addSeparator();
        //konec deklarace polozky "clear traces" v menu "simulation"
//        Submenu pro vyber druhu prepoctu rychlosti castic
        //a submenu

        submenu = new JMenu("Change velocity method:");
        ButtonGroup group = new ButtonGroup();
        for (int i = 0;i<Main.cptMet.length;i++){
        final String nm = Main.cptMet[i].getName();
        rbMenuItem = new JRadioButtonMenuItem(nm);
        rbMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    Main.mthdName = nm;
                }
            });
        if (i == 0){
            rbMenuItem.setSelected(true);
            Main.mthdName = nm;
        }
        group.add(rbMenuItem);
        submenu.add(rbMenuItem);
        }
        menuSimulation.add(submenu);
//        konec submenu pro vyber druhu prepoctu rychlosti castic
        //deklarace polozky "about" v menu "about"
        menuItAbout = new JMenuItem("About...",
                KeyEvent.VK_T);
        menuItAbout.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_A, ActionEvent.CTRL_MASK));
        menuItAbout.getAccessibleContext().setAccessibleDescription(
                "Open the About window");
        menuItAbout.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
//                JOptionPane.showMessageDialog(null, "Je to spravne nastavene");
                AboutFrame.setVisible(true);
            }
        });
        menuAbout.add(menuItAbout);
        //konec deklarace polozky "clear traces" v menu "simulation"

        mainMenu.add(menuFile);
        mainMenu.add(menuSimulation);
//                mainMenu.add(menuPtcs);
        mainMenu.add(menuAbout);
//        mainFrame.setComponentZOrder(mainMenu, mainFrame.getComponentCount()+1);


        mainFrame.setJMenuBar(mainMenu);
        //Konec pridani hlavniho menu
        ///////////////////////////////////////////////////////////////////////
        new Thread(platno).start();
        //zjisteni sirky okraju okna a zmena velikosti okna

        Insets insets = mainFrame.getInsets();
        int insetwidth = insets.left + insets.right;
        int insetheight = insets.top + insets.bottom;
        int h = mainMenu.getHeight();


        mainFrame.setSize(psim.Main.CLIENT_WIDTH_PX + insetwidth,
                psim.Main.CLIENT_HEIGHT_PX + insetheight + h + 56);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible(true);
    }
}
